package cn.chiship.framework.business.biz.member.service.impl;

import cn.chiship.framework.business.biz.member.enmus.MemberComeSourceEnum;
import cn.chiship.framework.business.biz.member.pojo.dto.MemberUserDto;
import cn.chiship.framework.business.biz.member.pojo.dto.MemberUserModifyDto;
import cn.chiship.framework.business.biz.member.pojo.dto.MemberUserRegisterDto;
import cn.chiship.framework.common.enums.UserSecondTypeEnum;
import cn.chiship.framework.business.biz.member.entity.MemberUserBind;
import cn.chiship.framework.business.biz.member.entity.MemberUserBindExample;
import cn.chiship.framework.business.biz.member.pojo.dto.MemberModifyPasswordDto;
import cn.chiship.framework.business.biz.member.service.MemberUserBindService;
import cn.chiship.framework.third.core.common.ThirdApplicationOauthTypeEnum;
import cn.chiship.framework.upms.biz.base.service.impl.AsyncMessageNotificationService;
import cn.chiship.framework.upms.biz.system.pojo.dto.UpmsNoticeSystemDto;
import cn.chiship.framework.upms.biz.system.service.UpmsNoticeService;
import cn.chiship.framework.upms.biz.system.service.UpmsRegionService;
import cn.chiship.framework.upms.core.enums.NoticeModuleTypeEnums;
import cn.chiship.framework.upms.core.enums.NoticePriorityEnums;
import cn.chiship.framework.upms.core.enums.NoticeScopeEnums;
import cn.chiship.sdk.cache.service.UserCacheService;
import cn.chiship.sdk.cache.util.JwtUtil;
import cn.chiship.sdk.cache.vo.CacheUserVO;
import cn.chiship.sdk.core.base.BaseResult;
import cn.chiship.sdk.core.base.constants.BaseTipConstants;
import cn.chiship.sdk.core.encryption.Md5Util;
import cn.chiship.sdk.core.enums.BaseResultEnum;
import cn.chiship.sdk.core.enums.UserTypeEnum;
import cn.chiship.sdk.core.util.ObjectUtil;
import cn.chiship.sdk.core.util.RandomUtil;
import cn.chiship.sdk.core.util.StringUtil;
import cn.chiship.sdk.framework.base.BaseServiceImpl;
import cn.chiship.framework.business.biz.member.mapper.MemberUserMapper;
import cn.chiship.framework.business.biz.member.entity.MemberUser;
import cn.chiship.framework.business.biz.member.entity.MemberUserExample;
import cn.chiship.framework.business.biz.member.service.MemberUserService;
import cn.chiship.sdk.framework.pojo.dto.AppletLoginOrRegisterDto;
import cn.chiship.sdk.framework.pojo.dto.UserForgotPasswordDto;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.swagger.annotations.ApiModelProperty;
import org.hibernate.validator.constraints.Length;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import javax.annotation.Resource;
import javax.validation.constraints.NotEmpty;

import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.*;

/**
 * 会员业务接口实现层 2022/2/23
 *
 * @author lijian
 */
@Service
public class MemberUserServiceImpl extends BaseServiceImpl<MemberUser, MemberUserExample> implements MemberUserService {

    private static final Logger LOGGER = LoggerFactory.getLogger(MemberUserServiceImpl.class);

    @Resource
    MemberUserMapper memberUserMapper;

    @Resource
    MemberUserBindService memberUserBindService;

    @Resource
    UserCacheService userCacheService;

    @Resource
    AsyncMessageNotificationService asyncMessageNotificationService;

    @Resource
    UpmsNoticeService upmsNoticeService;

    @Resource
    UpmsRegionService upmsRegionService;

    @Override
    public BaseResult selectDetailsByPrimaryKey(Object id) {
        Map<String, Object> result = new HashMap<>(16);
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(id);
        if (StringUtil.isNull(memberUser)) {
            return BaseResult.error("查无此用户！");
        }

        JSONObject json = JSON.parseObject(JSON.toJSONString(memberUser));
        json.put("_regionLevel1", upmsRegionService.getCacheRegionNameById(memberUser.getRegionLevel1()));
        json.put("_regionLevel2", upmsRegionService.getCacheRegionNameById(memberUser.getRegionLevel2()));
        json.put("_regionLevel3", upmsRegionService.getCacheRegionNameById(memberUser.getRegionLevel3()));
        json.put("_regionLevel4", upmsRegionService.getCacheRegionNameById(memberUser.getRegionLevel4()));
        result.put("memberUser", json);
        MemberUserBindExample memberUserBindExample = new MemberUserBindExample();
        memberUserBindExample.createCriteria().andUserIdEqualTo(memberUser.getId());
        memberUserBindExample.setOrderByClause("bind_time desc");
        List<MemberUserBind> memberUserBinds = memberUserBindService.selectByExample(memberUserBindExample);
        result.put("binds", memberUserBinds);
        return BaseResult.ok(result);
    }

    @Override
    public BaseResult login(String username, String password, String ip) {
        /**
         * 根据手机号查找用户
         */
        MemberUserExample memberUserExample = new MemberUserExample();
        memberUserExample.createCriteria().andMobileEqualTo(username);
        memberUserExample.or(memberUserExample.createCriteria().andUserNameEqualTo(username));
        List<MemberUser> memberUsers = memberUserMapper.selectByExample(memberUserExample);
        if (memberUsers.isEmpty()) {
            return BaseResult.error(BaseResultEnum.USER_IS_EXIST_NO, null);
        }

        MemberUser memberUser = memberUsers.get(0);
        if (!Md5Util.md5(password + memberUser.getSalt()).equals(memberUser.getPassword())) {
            return BaseResult.error(BaseResultEnum.ERROR_PASSWORD, null);
        }
        memberUser.setLastLoginIp(ip);
        memberUser.setLastLoginTime(System.currentTimeMillis());
        super.updateByPrimaryKeySelective(memberUser);
        return doLogin(memberUser);
    }

    @Override
    public BaseResult mobileLogin(String mobile, String ip) {
        /**
         * 根据手机号查找用户
         */
        MemberUserExample memberUserExample = new MemberUserExample();
        memberUserExample.createCriteria().andMobileEqualTo(mobile);
        List<MemberUser> memberUsers = memberUserMapper.selectByExample(memberUserExample);
        MemberUser memberUser;
        if (memberUsers.isEmpty()) {
            return BaseResult.error(BaseResultEnum.USER_IS_EXIST_NO, "手机号不存在");
        }
        memberUser = memberUsers.get(0);
        memberUser.setLastLoginIp(ip);
        memberUser.setLastLoginTime(System.currentTimeMillis());
        super.updateByPrimaryKeySelective(memberUser);
        return doLogin(memberUser);
    }

    @Override
    public BaseResult appletLogin(String appId, String openId, String ip) {
        MemberUserBindExample memberUserBindExample = new MemberUserBindExample();
        memberUserBindExample.createCriteria().andBindValueEqualTo(openId).andAppIdEqualTo(appId);
        List<MemberUserBind> memberUserBinds = memberUserBindService.selectByExample(memberUserBindExample);
        if (memberUserBinds.isEmpty()) {
            return BaseResult.ok(BaseResult.error("不存在的用户绑定信息，请先注册！"));
        }
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(memberUserBinds.get(0).getUserId());
        if (ObjectUtil.isEmpty(memberUser)) {
            return BaseResult.ok(BaseResult.error("不存在的用户信息，请先注册！"));
        }
        return BaseResult.ok(doLogin(memberUser));
    }

    @Override
    public BaseResult register(MemberUserRegisterDto memberUserRegisterDto) {
        String passwordAgain = memberUserRegisterDto.getPasswordAgain();
        String password = memberUserRegisterDto.getPassword();
        String mobile = memberUserRegisterDto.getMobile();
        if (!password.equals(passwordAgain)) {
            return BaseResult.error("确认密码输入错误！");
        }
        MemberUserExample memberUserExample = new MemberUserExample();
        memberUserExample.createCriteria().andMobileEqualTo(mobile);
        if (memberUserMapper.countByExample(memberUserExample) > 0) {
            return BaseResult.error("改手机号已注册,请重新输入！");
        }
        MemberUser user = new MemberUser();
        user.setMobile(mobile);
        user.setRealName(memberUserRegisterDto.getRealName());
        MemberComeSourceEnum memberComeSourceEnum = memberUserRegisterDto.getComeSourceEnum();
        if (!StringUtil.isNull(memberComeSourceEnum)) {
            user.setComeSources(memberComeSourceEnum.getSources());
        }
        user.setWallet(BigDecimal.ZERO);
        super.insertSelective(user);
        return doLogin(user);
    }

    /**
     * 授权注册
     *
     * @param appId
     * @param appletLoginOrRegisterDto
     * @param thirdApplicationOauthTypeEnum
     * @param ip
     * @return
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public BaseResult grantAuthRegister(String appId, AppletLoginOrRegisterDto appletLoginOrRegisterDto,
                                        ThirdApplicationOauthTypeEnum thirdApplicationOauthTypeEnum, String ip) {
        return doThirdApplicationRegister(appId, appletLoginOrRegisterDto.getOpenId(),
                appletLoginOrRegisterDto.getMobile(), appletLoginOrRegisterDto.getAvatar(),
                appletLoginOrRegisterDto.getNickName(), ip, thirdApplicationOauthTypeEnum);
    }

    public BaseResult doThirdApplicationRegister(String appId, String oathId, String mobile, String avatar,
                                                 String nickName, String loginIp, ThirdApplicationOauthTypeEnum thirdApplicationOauthTypeEnum) {
        MemberUserBindExample memberUserBindExample = new MemberUserBindExample();
        memberUserBindExample.createCriteria().andBindKeyEqualTo(thirdApplicationOauthTypeEnum.getType())
                .andBindValueEqualTo(oathId).andAppIdEqualTo(appId);
        List<MemberUserBind> memberUserBinds = memberUserBindService.selectByExample(memberUserBindExample);
        /**
         * 根据手机号查找用户
         */
        MemberUserExample memberUserExample = new MemberUserExample();
        memberUserExample.createCriteria().andMobileEqualTo(mobile);
        List<MemberUser> memberUsers = memberUserMapper.selectByExample(memberUserExample);
        MemberUser memberUser;
        if (memberUsers.isEmpty()) {
            /**
             * 判断三方授权码是否存在，若存在，提示已经注册
             */
            if (!memberUserBinds.isEmpty()) {
                return BaseResult.error("该授权码已绑定其他账号，但与手机号不匹配,请联系管理员处理!");
            }
            /**
             * 不存在则注册
             */
            MemberUser user = new MemberUser();
            user.setMobile(mobile);
            MemberComeSourceEnum memberComeSourceEnum = MemberComeSourceEnum
                    .fromThirdApplicationOauthTypeEnum(thirdApplicationOauthTypeEnum);
            if (!StringUtil.isNull(memberComeSourceEnum)) {
                user.setComeSources(memberComeSourceEnum.getSources());
            }
            user.setWallet(BigDecimal.ZERO);
            super.insertSelective(user);
            memberUser = user;
        } else {
            memberUser = memberUsers.get(0);
        }
        if (memberUserBinds.isEmpty()) {
            MemberUserBind memberUserBind = new MemberUserBind();
            memberUserBind.setAppId(appId);
            memberUserBind.setUserId(memberUser.getId());
            memberUserBind.setBindKey(thirdApplicationOauthTypeEnum.getType());
            memberUserBind.setBindValue(oathId);
            memberUserBind.setBindTime(System.currentTimeMillis());
            memberUserBind.setBindNickName(nickName);
            memberUserBind.setBindAvatar(avatar);
            memberUserBindService.insertSelective(memberUserBind);
        }
        memberUser.setNickName(nickName);
        memberUser.setAvatar(avatar);
        memberUser.setLastLoginIp(loginIp);
        memberUser.setLastLoginTime(System.currentTimeMillis());
        super.updateByPrimaryKeySelective(memberUser);

        UpmsNoticeSystemDto upmsNoticeSystemDto = new UpmsNoticeSystemDto("三方应用绑定成功",
                String.format("您已成功绑定 %s", thirdApplicationOauthTypeEnum.getDesc()),
                NoticePriorityEnums.NOTICE_PRIORITY_LOW, NoticeModuleTypeEnums.NOTICE_MODULE_TYPE_DEFAULT,
                UserTypeEnum.MEMBER, memberUser.getId(), memberUser.getRealName());
        asyncMessageNotificationService.sendSystemMsg(upmsNoticeSystemDto);
        return doLogin(memberUser);
    }

    BaseResult doLogin(MemberUser memberUser) {
        CacheUserVO userVO = new CacheUserVO(UserTypeEnum.MEMBER);
        userVO.setSubUserType(UserSecondTypeEnum.MEMBER.getType());
        userVO.setMobile(memberUser.getMobile());
        userVO.setUsername(memberUser.getUserName());
        userVO.setId(memberUser.getId());
        userVO.setRealName(memberUser.getRealName());
        userVO.setAvatar(memberUser.getAvatar());
        userVO.setEmail(memberUser.getEmail());
        userVO.setNickName(memberUser.getNickName());
        userVO.setExtInfo(memberUser);
        String accessToken = JwtUtil.createToken(userVO);
        userCacheService.cacheUser(accessToken, userVO);
        return BaseResult.ok(accessToken);
    }

    @Override
    public BaseResult modifyUserName(String id, String userName) {
        if (StringUtil.isNullOrEmpty(userName)) {
            return BaseResult.error("用户名不能为空");
        }
        if (userName.length() > 10 || userName.length() < 5) {
            return BaseResult.error("用户名只允许5-10个字符");
        }
        MemberUserExample memberUserExample = new MemberUserExample();
        memberUserExample.createCriteria().andUserNameEqualTo(userName).andIdNotEqualTo(id);
        if (memberUserMapper.countByExample(memberUserExample) > 0) {
            return BaseResult.error("用户名已存在，请重新输入！");
        }
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(id);
        if (StringUtil.isNull(memberUser)) {
            return BaseResult.error("查无此用户！");
        }
        memberUser.setUserName(userName);
        super.updateByPrimaryKeySelective(memberUser);
        return doLogin(memberUser);
    }

    @Override
    public BaseResult modifyNickName(String id, String nickName) {
        if (StringUtil.isNullOrEmpty(nickName)) {
            return BaseResult.error("昵称不能为空");
        }
        if (nickName.length() > 10 || nickName.length() < 2) {
            return BaseResult.error("昵称只允许2-10个字符");
        }
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(id);
        if (StringUtil.isNull(memberUser)) {
            return BaseResult.error("查无此用户！");
        }
        memberUser.setNickName(nickName);
        super.updateByPrimaryKeySelective(memberUser);
        return doLogin(memberUser);
    }

    @Override
    public BaseResult modifyUser(MemberUserModifyDto memberUserModifyDto, String id) {
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(id);
        if (StringUtil.isNull(memberUser)) {
            return BaseResult.error("查无此用户！");
        }
        if (StringUtil.isNullOrEmpty(memberUser.getRealName())) {
            memberUser.setRealName(memberUserModifyDto.getRealName());
        }
        if (!StringUtil.isNull(memberUserModifyDto.getGender())) {
            memberUser.setGender(memberUserModifyDto.getGender());
        }
        memberUser.setAvatar(memberUserModifyDto.getAvatar());
        memberUser.setNickName(memberUserModifyDto.getNickName());
        memberUser.setSignature(memberUserModifyDto.getSignature());
        memberUser.setIntroduction(memberUserModifyDto.getIntroduction());
        memberUser.setEmail(memberUserModifyDto.getEmail());
        memberUser.setBirthday(memberUserModifyDto.getBirthday());
        memberUser.setRegionLevel1(memberUserModifyDto.getRegionLevel1());
        memberUser.setRegionLevel2(memberUserModifyDto.getRegionLevel2());
        memberUser.setRegionLevel3(memberUserModifyDto.getRegionLevel3());
        memberUser.setRegionLevel4(memberUserModifyDto.getRegionLevel4());
        memberUser.setAddress(memberUserModifyDto.getAddress());
        super.updateByPrimaryKeySelective(memberUser);
        return doLogin(memberUser);
    }

    @Override
    public BaseResult forgotPassword(UserForgotPasswordDto userForgotPasswordDto) {
        String passwordAgain = userForgotPasswordDto.getPasswordAgain();
        String password = userForgotPasswordDto.getPassword();
        String mobile = userForgotPasswordDto.getMobile();
        if (!password.equals(passwordAgain)) {
            return BaseResult.error("确认密码输入错误！");
        }
        MemberUserExample memberUserExample = new MemberUserExample();
        memberUserExample.createCriteria().andMobileEqualTo(mobile);
        List<MemberUser> memberUsers = memberUserMapper.selectByExample(memberUserExample);
        if (memberUsers.isEmpty()) {
            return BaseResult.error("输入的手机号不存在,请重新输入！");
        }
        MemberUser memberUser = memberUsers.get(0);
        memberUser.setSalt(RandomUtil.uuidLowerCase());
        memberUser.setPassword(Md5Util.md5(password + memberUser.getSalt()));
        memberUser.setGmtModified(System.currentTimeMillis());
        return super.updateByPrimaryKeySelective(memberUser);
    }

    @Override
    public BaseResult modifyPassword(MemberModifyPasswordDto memberModifyPasswordDto, CacheUserVO cacheUserVO) {
        if (!cacheUserVO.getMobile().equals(memberModifyPasswordDto.getMobile())) {
            return BaseResult.error("手机号码不匹配");
        }
        if (memberModifyPasswordDto.getOldPassword().equals(memberModifyPasswordDto.getNewPassword())) {
            return BaseResult.error(BaseResultEnum.ERROR_PASSWORD, "新旧密码不能一致");
        }
        if (!memberModifyPasswordDto.getNewPassword().equals(memberModifyPasswordDto.getNewPasswordAgain())) {
            return BaseResult.error("确认密码输入错误！");
        }
        MemberUser memberUser = memberUserMapper.selectByPrimaryKey(cacheUserVO.getId());
        if (!Md5Util.md5(memberModifyPasswordDto.getOldPassword() + memberUser.getSalt())
                .equals(memberUser.getPassword())) {
            return BaseResult.error(BaseResultEnum.ERROR_PASSWORD, "旧密码输入错误");
        }
        memberUser.setSalt(RandomUtil.uuidLowerCase());
        memberUser.setPassword(Md5Util.md5(memberModifyPasswordDto.getNewPassword() + memberUser.getSalt()));
        memberUser.setGmtModified(System.currentTimeMillis());
        return super.updateByPrimaryKeySelective(memberUser);
    }

    @Override
    public BaseResult publishNotice(String noticeId, String scope) {
        if (!Arrays.asList(NoticeScopeEnums.NOTICE_SCOPE_ALL.getType(), NoticeScopeEnums.NOTICE_SCOPE_USER.getType())
                .contains(scope)) {
            return BaseResult.error("接收范围不正确");
        }
        List<String> userIds = new ArrayList<>();
        if (NoticeScopeEnums.NOTICE_SCOPE_ALL.getType().equals(scope)) {
            // 保留
        }
        upmsNoticeService.publish(noticeId, userIds);
        return BaseResult.ok();
    }

    @Override
    public BaseResult walletByUserId(String userId) {
        MemberUser memberUser = selectByPrimaryKey(userId);
        if (memberUser == null) {
            return BaseResult.error("无效的会员标识");
        }
        Map<String, Object> result = new HashMap<>(7);
        result.put("realName", memberUser.getRealName());
        result.put("mobile", memberUser.getMobile());
        result.put("wallet", memberUser.getWallet());
        return BaseResult.ok(result);
    }
}
